package Android.SinYateClient;

import java.io.ByteArrayInputStream;
import java.io.InputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

class XMLParser {
	public XMLParser() {
		DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
		try {
			docBuilder = dbfac.newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		}
	}

	DocumentBuilder docBuilder = null;

	public String getPollingXML(String clientid) {
		Document doc = docBuilder.newDocument();

		// create the root element and add it to the document
		Element root = doc.createElement("sinyate");
		doc.appendChild(root);

		Element id = doc.createElement("id");
		Element deviceid = doc.createElement("deviceid");
		Element assignment = doc.createElement("assignment");
		Element polling = doc.createElement("polling");

		assignment.appendChild(polling);
		deviceid.appendChild(doc.createTextNode(clientid));
		id.appendChild(deviceid);

		root.appendChild(id);
		root.appendChild(assignment);

		return provideXMLString(doc);
	}

	public static String provideXMLString(Document doc) {
		Node roott = doc.getDocumentElement(); // getFirstChild();
		String s = "%3C" + roott.getNodeName() + "%3E";
		s += provideXMLStringRec(roott);
		s += "%3C/" + roott.getNodeName() + "%3E";
		return s;
	}

	private static String provideXMLStringRec(Node n) {
		String s = "";
		for (int i = 0; i < n.getChildNodes().getLength(); i++) {
			Node child = n.getChildNodes().item(i);
			if (child.getNodeType() == Document.ELEMENT_NODE) {

				s += "%3C" + child.getNodeName() + "%3E";
			}

			if (child.hasChildNodes()) {
				s += provideXMLStringRec(child);

			} else if (child.getNodeValue() != null) {
				String c = child.getNodeValue();
				c = c.replaceAll(" ", "%20");

				s += c;

			}

			if (child.getNodeType() == Document.ELEMENT_NODE) {

				s += "%3C/" + child.getNodeName() + "%3E";
			}
		}
		return s;
	}

	public String getConfirmationXML(String clientid) {

		Document doc = docBuilder.newDocument();
		Element root = doc.createElement("sinyate");
		doc.appendChild(root);

		Element id = doc.createElement("id");
		Element deviceid = doc.createElement("deviceid");
		Element assignment = doc.createElement("assignment");
		Element polling = doc.createElement("confirmation");

		assignment.appendChild(polling);
		deviceid.appendChild(doc.createTextNode(clientid));
		id.appendChild(deviceid);

		root.appendChild(id);
		root.appendChild(assignment);

		return provideXMLString(doc);
	}

	public Document getRegistrationXML(AndroidClient ac) {
		DeviceInfo di = new DeviceInfo(ac);
		Document doc = docBuilder.newDocument();
		Element root = doc.createElement("sinyate");

		Element id = doc.createElement("id");
		Element deviceid = doc.createElement("deviceid");
		Element assignment = doc.createElement("assignment");
		Element information = doc.createElement("configuration");

		Node xmltext = doc.createTextNode("0");

		deviceid.appendChild(xmltext);
		id.appendChild(deviceid);
		root.appendChild(id);

		Element info1 = doc.createElement("name");
		Node xml1 = doc.createTextNode(di.getName());
		info1.appendChild(xml1);
		information.appendChild(info1);

		Element info2 = doc.createElement("os");
		Node xml2 = doc.createTextNode("Google Android");
		info2.appendChild(xml2);
		information.appendChild(info2);

		Element info3 = doc.createElement("model");
		Node xml3 = doc.createTextNode("emulator");
		info3.appendChild(xml3);
		information.appendChild(info3);

		Element info4 = doc.createElement("family");
		Node xml4 = doc.createTextNode("Android");
		info4.appendChild(xml4);
		information.appendChild(info4);

		// Element info5 = doc.createElement("type");
		// Node xml5 = doc.createTextNode("emulator");
		// info5.appendChild(xml5);
		// information.appendChild(info5);

		Element info6 = doc.createElement("browser");
		Node xml6 = doc.createTextNode("Android Browser");
		info6.appendChild(xml6);
		information.appendChild(info6);

		Element info7 = doc.createElement("application");
		Node xml7 = doc.createTextNode("camera");
		info7.appendChild(xml7);
		information.appendChild(info7);

		assignment.appendChild(information);
		root.appendChild(assignment);
		doc.appendChild(root);

		return doc;
	}

	private void schrijf(NodeList list) {
		for (int i = 0; i < list.getLength(); i++) {
			// Get element
			Element element = (Element) list.item(i);
			System.out.println(element.getNodeName());
		}
	}

	public Assignment getAssignment(String xml) {
		// Create a factory
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

		// belangrijk, dit is een vereiste, anders problemen bij interpreter
		// factory.setValidating(true);
		// factory.setIgnoringElementContentWhitespace(true);
		// Use the factory to create a builder
		// factory.setNamespaceAware(true);

		DocumentBuilder builder;
		Document doc = null;
		try {
			builder = factory.newDocumentBuilder();

			InputStream is = new ByteArrayInputStream(xml.getBytes("UTF-8"));

			doc = builder.parse(is);

		} catch (Exception e) {
				e.printStackTrace();
		}

		Assignment assignment = null;

		// <sinyate>
		NodeList nodelist = doc.getChildNodes();

		// <id><assignment>
		nodelist = nodelist.item(0).getChildNodes();

		if (nodelist.getLength() > 1) {
			assignment = new Assignment();
			assignment.setXML(doc);
			// <id>
			Node firstchild = nodelist.item(0);
			NodeList ids = firstchild.getChildNodes();

			if (ids.item(0).getNodeName().equals("testid")) {
				assignment
						.setTestId(ids.item(0).getFirstChild().getNodeValue());
				assignment.setDeviceId(ids.item(1).getFirstChild()
						.getNodeValue());
			} else {

				assignment.setDeviceId(ids.item(0).getFirstChild()
						.getNodeValue());
				assignment
						.setTestId(ids.item(1).getFirstChild().getNodeValue());
			}

			// <assignment>
			Node assign = nodelist.item(1);

			assignment.setAssignmentType("assignment");
			// <configuration>
			NodeList assignnodelist = assign.getChildNodes();
			for (int i = 0; i < assignnodelist.getLength(); i++) {
				if (assignnodelist.item(i).getNodeName()
						.equals(("application"))) {
					
					Task task = new Task("application");
					task.setTaskId(Integer.parseInt(assignnodelist.item(i)
							.getAttributes().item(0).getNodeValue()));
					for (int j = 0; j < assignnodelist.item(i).getChildNodes()
							.getLength(); j++) {
					
						task.setParameterValue(assignnodelist.item(i)
								.getChildNodes().item(j).getNodeName(),
								assignnodelist.item(i).getChildNodes().item(j)
										.getFirstChild().getNodeValue());
					}
					assignment.addTask(task);
				}
				if (assignnodelist.item(i).getNodeName().equals("screenshot")) {
					Task task = new Task("screenshot");
					task.setTaskId(Integer.parseInt(assignnodelist.item(i)
							.getAttributes().item(0).getNodeValue()));
					for (int j = 0; j < assignnodelist.item(i).getChildNodes()
							.getLength(); j++) {
						task.setParameterValue(assignnodelist.item(i)
								.getChildNodes().item(j).getNodeName(),
								assignnodelist.item(i).getChildNodes().item(j)
										.getFirstChild().getNodeValue());
					}
					assignment.addTask(task);
				}
				if (assignnodelist.item(i).getNodeName().equals("keystroke")) {
					// TODO
				}
				if (assignnodelist.item(i).getNodeName().equals("information")) {
					// TODO
				}
				if (assignnodelist.item(i).getNodeName()
						.equals("configuration")) {

					Task task = new Task("configuration");

					task.setTaskId(Integer.parseInt(assignnodelist.item(i)
							.getAttributes().item(0).getNodeValue()));
					for (int j = 0; j < assignnodelist.item(i).getChildNodes()
							.getLength(); j++) {
						task.setParameterValue(assignnodelist.item(i)
								.getChildNodes().item(j).getNodeName(),
								assignnodelist.item(i).getChildNodes().item(j)
										.getFirstChild().getNodeValue());
					}
					assignment.addTask(task);
	
				}
			}
		}
		// System.out.println("deviceid: "+assignment.getDeviceId());
		// System.out.println("server(1): "+assignment.getTaskList().get(0).getParameterValue("server"));
		return assignment;
	}
}
